﻿using Modbus.Device;

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AutoWelding.Views.Transmission
{
    public partial class TransmissionForm : Form
    {
        public TransmissionForm()
        {
            InitializeComponent();
        }
        private SerialPort serialPort = new SerialPort();//串口初始化
        private CancellationTokenSource _cts; // 用于取消读取任务
        private Task _readTask;              // 读取任务引用---开启读取
        private void TransmissionForm_Load(object sender, EventArgs e)
        {
            //初始化串口选择数据
            LoadComboBoxData();
        }


        #region 定义5个串口下拉框绑定数据源------数组
        //波特率
        private string[] baudRates = new string[] {"4800", "9600", "19200", "38400", "57600", "115200" };
        //停止位
        private string[] stopBits = new string[] {"One", "Two","OnePointFive" };
        //数据位
        private string[] dataBits = new string[] {"5","6","7","8" };
        //校验位
        private string[] checkDigBits = new string[] {"None", "Odd", "Even", "Mark", "Space" };
        //获取可用串口名称并放到一个数组中
        private string[] portNames = SerialPort.GetPortNames();
        #endregion
        /// <summary>
        /// 初始化 串口选择数据
        /// </summary>
        private void LoadComboBoxData()
        {
            ///串口名称下拉框
           cbx_portName.Items.AddRange(portNames);
            //默认选中第一个
            cbx_portName.SelectedIndex = 0;

            ///波特率下拉框
            cbx_baudRate.Items.AddRange(baudRates);
            //默认选中 9600
            cbx_baudRate.SelectedIndex = 1;

            ///数据位下拉框
            cbx_dataBits.Items.AddRange(dataBits);
            //默认选中 8
            cbx_dataBits.SelectedIndex = 3;

            ///停止位下拉框
            cbx_stopBits.Items.AddRange(stopBits);
            //默认选中 0
            cbx_stopBits.SelectedIndex = 0;

            ///校验位下拉框
            cbx_checkDigBit.Items.AddRange(checkDigBits);
            //默认选中 None
            cbx_checkDigBit.SelectedIndex = 0;


        }

        /// <summary>
        /// 打开或者关闭串口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void btn_openOrClosePort_Click(object sender, EventArgs e)
        {
            try
            {
                if (!serialPort.IsOpen)
                {
                    serialPort.PortName = cbx_portName.Text;
                    serialPort.BaudRate = Convert.ToInt32(cbx_baudRate.Text);
                    serialPort.DataBits = Convert.ToInt32(cbx_dataBits.Text);
                    serialPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), cbx_stopBits.Text);
                    //校验位
                    serialPort.Parity = (Parity)Enum.Parse(typeof(Parity), cbx_checkDigBit.Text);

                    serialPort.Open();
                    btn_openOrClosePort.Text = "关闭串口";

                    //启动读取任务
                    _cts = new CancellationTokenSource();
                    _readTask = ReadDataAsync(_cts.Token);
                }
                else
                {
                    //取消读取任务
                    _cts.Cancel();
                    try
                    {
                        await _readTask; // 等待任务完成（包括异常处理）
                    }
                    catch (OperationCanceledException)
                    {
                        Console.WriteLine("读取任务已取消");
                    }
                    finally
                    {
                        serialPort.Close();
                        btn_openOrClosePort.Text = "打开串口";
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("串口操作失败！请核实原因并重新打开");
            }
        }

        // 定义Label分组数组（对应45个Label）
        private Label[] labelsGroup;
        /// <summary>
        /// 通过Modbus读取数据
        /// </summary>
        /// <returns></returns>
        private async Task ReadDataAsync(CancellationToken token)
        {
            try
            {
                using (IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(serialPort))
                {
                    master.Transport.ReadTimeout = 2000;
                    master.Transport.Retries = 3;

                    // 22~36：共15个Label（36-22+1=15）
                    var group1 = Enumerable.Range(22, 15)
                    .Select(num => this.Controls.Find($"label{num}", true).FirstOrDefault() as Label)
                    .Where(lbl => lbl != null)
                    .ToArray();

                    // 52~66：共15个Label
                    var group2 = Enumerable.Range(52, 15)
                        .Select(num => this.Controls.Find($"label{num}", true).FirstOrDefault() as Label)
                        .Where(lbl => lbl != null)
                        .ToArray();

                    // 67~81：共15个Label
                    var group3 = Enumerable.Range(67, 15)
                        .Select(num => this.Controls.Find($"label{num}", true).FirstOrDefault() as Label)
                        .Where(lbl => lbl != null)
                        .ToArray();

                    // 合并为45个Label的数组
                    labelsGroup = group1.Concat(group2).Concat(group3).ToArray();

                    while (!token.IsCancellationRequested)
                    {
                        // 批量读取10个寄存器
                        ushort[] values = master.ReadHoldingRegisters(1, 0, 45);

                        // 更新UI
                        this.Invoke((MethodInvoker)delegate {
                            for (int i = 0; i < values.Length && i < labelsGroup.Length; i++)
                            {
                                labelsGroup[i].Text = values[i].ToString();
                            }
                        });

                        await Task.Delay(200);
                    }
                }
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("任务被取消");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"读取失败: {ex.Message}");
            }
        }
    }
}
